The problem isn't that the function is calling the GUI too many times; it's that it's blocking the event loop, which causes the window to freeze. Every cycle in the event loop, tkinter (or actually the tk backend) handles events, invokes callbacks, etc. and then hands control over to the operating system for a little bit. If the former takes too long, and the latter is not handled in a timely manner, the operating system thinks something is wrong (which causes the "not responding" title tag in Windows, for example.)
The whole point of what I was saying was that you attach your function to a callback. By breaking the processing into chunks then returning, you ensure you never run for too long. By making your processing into an
object you ensure that state is saved between each call to the function. The advantage of knowing how to do this general kind of thing is that it will work with
any language and framework.
Any framework will give you some sort of "hooks" (which might be called callbacks, events, update function, whatever: it doesn't matter) that run per-frame and you can attach your own code to, so that you can run your own stuff with it without needing to spawn an entire new thread for it. Just read the documentation, find out how you're expected to attach code to it that runs every frame, then make sure that your amount of processing done per call is some reasonably limited amount. Which is where using an object to store processing state is useful.
The reasons that your button-function was blocking was that your were attaching the whole load of processing to the button and not returning at intervals. e.g. in this example, what you do is attach a small function to the button instead, which sets some flags that "processing is started", then you have another function attached to whatever tkinter gives you that runs each frame, and each frame it checks whether there's any processing to do, does a bit, then returns. It'll keep running until processing is finished. Another advantage of doing this is having a real easy way to design dynamic progress bars. You can have your per-frame processing function return a value for the % of processing that's finished and then easily set some display elements to show it.