There's two reasons you might want to do it.
The first reason and the most common is when you partition flash memory into different blocks for different things and one block updates another block. Like the bootloader block updates the application block. Or the application block updates the block used for NVM storage.
The second reason is much much less common and is 'self-modifying code'. Where the application may decide to change its own code based on the code its running. I can't think of many examples for this because I don't think it's used much any more now that MCUs use flash memory. (Due to the problem of having to erase an entire flash page making it more compilated to change just one bit of code within a program). Also MCUs are much faster now and have much more storage so the advantages of self-modifying code kind of evaporated.
But an example might be a command causing the MCU to stop processing data and spend some time crunching hard-core math functions to update all its hard-coded lookup tables for a new mode of operation. Though if you wanted to do this today you'd probably just store the lookup table in a different block to the main application. Which would move this idea into the first category.
Or, another example is if the application code is extracting every little bit of performance out of the processor, or has very timing critical tasks to do, it might not be possible to add extra code to support many selectable operating modes. So it might internally reprogram one of its own functions between a few internally stored versions and cause a reboot to change operating modes. But this was a long time ago, when hardware was very slow and people were trying to gain speed any way they could
There's probably better examples of it though, it's not something i've ever had to do.