Application memory "use" is a fairly nebulous concept on any operating system.
If an application were to rely on the OS for all memory management performance would be unacceptable.
As a result, most if not all applications manage their own memory to a certain extent. That is certainly the case for Delphi applications.
A Delphi application manages its own heap, allocating (relatively) large chunks of memory from the OS and then handing that out in smaller 'pieces' for use within the application as needed. The application only then has to go back to ask for more memory from the OS if it runs out of that pre-allocated memory.
It also means that at any given time, some of that allocated memory is not actively in use within the application.
As memory use changes an application will return any excess memory back to the OS. The way that Delphi applications work this typically happens when an application is minimised, for example. As a result, if you minimise and then restore your application you may see the memory "in use" change quite dramatically. The mechanism that underpins this is sometimes used to force an application to return memory more aggressively by triggering the same process in response to an application simply going "idle", as opposed to being specifically minimised.
However, such techniques are simply addressing the perception of memory use as observed in Task Manager, not actually reducing real memory use.
The bottom line is that memory used by an application from the perspective of the OS may be very different than the actual memory in use.
In your case, a simplified view of what is happening is that memory is allocated for the strings required to add the items to the listbox. When you clear the listbox, the memory used for those strings is not returned to the system immediately as this quite expensive, instead it is simply marked as no longer in use (it will be returned to the system at some point, just not yet).
On your next iteration of the loop, when more strings are needed to add to the list box, an efficient memory manager (in the application) might identify that the previously used memory, not yet returned to the OS, could now be re-used. Of course, identifying this takes time, so it may be more efficient to simply use some "fresh" memory, even if that means asking the OS for more.
Returning memory to the OS is more complicated (and therefore 'more expensive', i.e. takes longer) than asking for more, since memory can only be returned in chunks, so even if you have only 10% of your application memory "in use", it may be that the 10% that is being used is spread right throughout that memory making it impossible for some, or perhaps even any, of that memory to be returned to the OS. You will often hear this situation referred to as memory "fragmentation".
This is why returning memory to the OS is more costly than allocating new memory, because of the work that has to be done to work out what memory can be safely returned.
Returning to your scenario:
After 2 iterations you accumulate two rounds of memory that has been used and is now marked as no longer used (within the application). From the OS perspective however, that application is still "using" that memory, since the OS has no idea of what's going on inside the applications own management of that memory. Repeat that enough times and you can easily accumulate lots of "allocated but not currently used" memory.
But this is not normally something you need to worry about - as well as returning memory to the OS when no longer needed and convenient to do so, an application will return memory when asked or told to do so by the OS, for example if the system is under memory pressure.
The fact that an operating system incorporates direct support for the possibility that an application may be "using" memory that it actually is not using and can be asked to release when required, should tell you that this is not unusual. In fact, it is expected.
Worth mentioning however is that the memory manager built-in to Delphi is replaceable.
The default memory manager in Delphi 7 is adequate, but numerous alternatives are available. Some of these are highly specialised but one general purpose memory manager in particular - FastMM - has proven to be such a significant improvement on the older Delphi memory manager that it was adopted as the new default memory manager from Delphi 2006 onwards.
It remains freely available as an open source project that you can easily incorporate in your own applications however, even in Delphi 7 (or even older versions). All that is involved is adding a single unit as the first entry in your DPR uses list.
FastMM offers higher resilience to memory fragmentation resulting in greater efficiency as well as improved overall performance, as compared to the default memory manager in Delphi 7. It also offers additional debugging tools such as memory leak detection and facilities for identifying other memory errors such as double-free'd objects and/or so-called 'dangling' pointers (to an extent).
You may find that using FastMM in your test case may have an impact on the perceived memory use in your case but, for the reasons explained, this test case itself is not something to be concerned with per se unless it presents an actual problem in your application.