Jeleeb, the short answer is that without the scalar subquery the function will run for every row. If it is in the "select" portion it will run for every row returned. If it is in the "where" portion it will run for every row evaluated. That means a SQL to PL/SQL context switch for every row. That is very expensive.
When you use a scalar subquery, it will cache the result of the function (up to a limit depending on your db version). If the same bind variable is used, it won't rerun the function, it will just take the value from the cache. It is significantly faster because it avoids the context switch AND it doesn't have to run the function.
In the case of
(select my_function(empno) from dual)
it won't actually help because the value of empno will be different for every row. Hence, it will need to run the query every time. So, there is no benefit. But, it doesn't really hurt either. So, if you are just in the habit of ALWAYS doing it, then you can decide to not do it when you are sure it won't help.
Regarding point 8, it's incredibly complicated to come up with rules as to when one way or another is faster. It's easier to have a representative data set and just test it out. I suspect with 23c the database may automatically rewrite the query based upon the data profile to get the best performance. We'll see if that happens, but for now, I suggest following point 1, and then using the method that gives you the best (fastest) result.
Juno Tasli
Oracle APEX developer
Great tips. Thnak you Anton.