How and where the function is used matters. For example, functions called from the WHERE clause of a SELECT statement can be a performance killer. We once had a statement similar to:
SELECT * FROM TRANSACTIONS T
WHERE IS_UGLY_TRANSACTION_CODE(T.TRANSACTION_CODE) = 'T' AND ...
The overall process was running way too slowly and the install date was headed our way way too quickly so I started instrumenting the code to figure out where the time was going. When I got the profiling report back I looked at it and saw that the job had processed 1000 transactions, and then noticed that IS_SALES_TRANSACTION had been called about half-a-million times. After a little thought and some study of the statement execution plan I realized that the routine in question was being used by the database as the primary filter in the query, and that this was causing two bad things to happen: first, the presence of the routine in the query was preventing an index from being used so the query was scanning the table, and secondly the routine was being called for every row in the table during the scan. Replacing the function call with equivalent checks on the TRANSACTION_CODE column dropped the runtime from 15 minutes to 5 seconds.