You could use your current query and get the size attribute of the list after the query finishes:
List<User> users = [SELECT Name, (SELECT id FROM Applications__r) FROM User];
for (User u : users) {
// do something with it...
u.Applications__r.size();
}
Alternatively, you can use an AggregateResult query which would query the child and group by the User Id lookup. This would not retrieve any information about Users that don't have any Applications, though. Also, if the User field is not required, all Applications that don't have a User would be put in the grouping where User__c is null.
// Assumes you have a Lookup called User__c
Map<Id, Integer> userAppCountMap = new Map<Id, Integer>();
for (AggregateResult aggRes : [
SELECT COUNT(ID) numApps, User__c userId
FROM Application__c
GROUP BY User__c
]) {
Id userId = (Id) aggRes.get('userId');
Integer numApps = (Integer) aggRes.get('numApps');
userAppCountMap.put(userId, numApps);
}