I don't think you can do it.
In formulas / merge fields syntax there's no way to go "up, up then down" (Application -> Opportunity -> Account -> down to Contacts related list). There's also nothing that would let you loop through Contacts (and display what? Ids? Names? Emails?). Roughly speaking you can only go up through dots.
You might want to explore path of "cross object workflow" rules but I imagine that when I add a new Contact to Account it should somehow "spread itself" to all related Applications? There's no straight way to fire a workflow on delete too - so you'd eventually end up with inaccurate list.
I'd say trigger was a good solution. Maybe it ws unoptimized but if it has to be in a field - tough.
There might be a fairly simple way of achieving that by embedding a visualforce page within Application page layout.
This should be doable with pure Visualforce (so technically there will be no Apex code ;))
Something as simple as
<apex:relatedList list="Contacts" subject="Application__c.Opportunity__r.AccountId" />
would be a good start (if you want your own layout and not a rel. list - you should be still able to pull it off with <apex:repeat>
or <apex:pageBlockTable>
.
There's one BUT here: it's not a field, just a display trick. Forget about using it in reports, mobile applications etc.
Another way - would it be acceptable to be 1 click away from these contacts? You could make a report "Account with Contacts", filter it by Id of one Account and later use "URL hacking" to change the filter depending on from which Application you'll click it. This link could be either a formula field or a real custom button/link. Technically - it's pure config, no apex & VF.
You can read more about URL hacking at Ray Dehler's excellent post and specifically about dynamic Reports here or here.