This is probably the best AskTom thread on it
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:865497961356 Its a little out of date. Where is referenced "open_cursors" for PLSQL, thats been changed, but the principle remains unchanged, namely:
worst case - hard parse everything, every SQL a new one
better - we do a parse call on everything, but because (for example) we are using bind variables, many of those parses become a soft parse
better again - as per above, but we set session_cached_cursor, so that those soft parses become "softer" (ie, they cost less). The price for that is we're holding onto more stuff in memory (hence the *potential* risk for ora-4031, but I would say unlikely).
best - parse once (hard parse) and then never parse again (not even soft) by holding cursors open as required. Sounds tough to do (and it is), but if you're using PL/SQL for all of your SQL... we do all of the heavy lifting for you. Otherwise, it becomes your job to manage.
So if you can get to "best" (ie, use PLSQL) then you're pretty much optimal. If you can't, then aim for "better again".