The developers might be right. In the .Net world, garbage collection and freeing memory happens when needed. I.e. if, there's plenty of memory available to the application, it may consume more and more, until the operating system does not allow more allocation. You shouldn't worry about that, unless it really causes problems.
Of course, there may be memory leaks, if the application does not properly dispose unmanaged resources, like sockets, file handlers, etc. Look at the operating system objects (in task manager, you can enable handles and user objects columns) to see how they grow.
As you stated, Application or Session object misusing can also be a cause.
I'm wondering why you would have 48 application pools (worker processes). This is overkill, and you do not need that at all.
The GC manages memory per process, and 400MB per process is not that much at all. Reduce the number of app pools to the nr. of cores - 1, and then stress test the application. If then it grows too much, you may be concerned about memory leaks.
Based on your additional information, yes, in that case the history list will grow indefinitely. Static objects are created once per application domain, and live until the appdomain lives.
I do not advise you to arbitrary remove the static keyword, unless you know that you do not break some application logic. Investigate why that data is collected anyway, and what it is used for. The code has another problem as well - it's not thread safe, it's behavior is undefined when 2 requests came in at the same time, and decide to add data to that list.
Better move your question to stackoverflow.com, as it's a programming question, and not administrative one.
If you are not in control off that code, and really want to just solve your memory problem, you can set your apppools to recycle after X number of requests, or after they get more than Y amount of memory - but again, that's not a real solution.