Oracle stores dates with an internal representation (which takes up 7 bytes; you can see how it's structured elsewhere, but you don't often need to be concerned about the details). The stored date has no intrinsic human-readable format. However you insert it it is stored the same way, not with any display format.
When you just query the date column like:
SELECT submission_date
FROM submissions
the database returns its internal representation and your client decides how to display it. In most clients it will use your session NLS settings, specifically NLS_DATE_FORMAT here. Based on your result 01-MAR-16 that appears to be DD-MON-RR.
whereas I want submission_date returned as 2016-03-01
If you want the date as a string in a specific format then use to_char(), as you have already tried:
SELECT to_char(submission_date, 'yyyy-mm-dd')
FROM submissions
which, as you say, results in 2016-03-01. You can also change your client's NLS settings to give that format by default, but it's better to be explicit in anything other than an ad hoc query.
You should generally only convert a date to a string as the final step for display, to control readable output. If you are manipulating dates or using them in a subquery or retrieving the results in an application (e.g. via a JDBC call) then keep it as a date throughout the processing - only format it right at the end for display.
If you do:
SELECT to_date(submission_date, 'yyyy-mm-dd')
FROM submissions
you are using a different function. to_date() is the opposite of to_char() - it converts a string into a date.
But... submission_date is already a date. That means that date is being implicitly converted to a string, using your NLS settings, and that string is then converted back to a date. So effectively that is:
SELECT to_date(to_char(submission_date), 'yyyy-mm-dd')
FROM submissions
which with your NLS setting is:
SELECT to_date(to_char(submission_date, 'DD-MON-RR'), 'yyyy-mm-dd')
FROM submissions
results in 01-MAR-16.
With your settings that should actually give you 16-MAR-01, not 01-MAR-16. And that is 0001-03-01. The (implied) conversion to_char(submission_date, 'DD-MON-RR') gives you the string '01-MAR-16', and the (explicit) conversion to_date('01-MAR-16', 'YYYY-MM-DD') converts the 01 as the year - as 0001 - and the day as 16.
Your client is then, again, displaying that resulting date using your NLS settings.
fiddle
You might be tempted to change your NLS settings to make it work, but again, resist that temptation for anything but ad hoc queries. You may end up with code that works fine for you today, but not for someone running your code later with different settings. If you're lucky they will get an error or something so obviously wrong they stop and fix it; but they might not notice or the effect might be subtle, and leave you with incorrect data that skews results or causes other errors years later.
Why am I getting different results with same date format?
You are using different functions, invoking implicit conversions, and relying on NLS settings.
CREATE TABLEstatement so we can see the exact types of your columns.