There is something rotten with the "F()" macro!
Everything sent with "F()" (for example client.print(F("POST /")); ) is sent char by char.
Everything sent without (for example client.print(url_address); ) is sent as a whole.
The F() macro as pointed out, stores the string in PROGMEM… Problem there — at least on the processors I've used where it's typically a thing — is that PROGMEM is 16-bit, not the usual 8-bit byte addressable. And the F() macro doesn't re-pack the string, so you end up with something like "H\0e\0l\0l\0o\0\0\0" actually being stored — it has no way of knowing exactly what you plan to do with that string, so it sacrifices a little memory for flexibility and ease of access (also, it forms a highly optimisable loop, so it should end up being pretty darned quick). Plus, you tend to have 8x or 16x as much PROGMEM as regular RAM, so it really usually doesn't actually matter for the kinds of tasks Arduino is aimed at (which is not professional high-end development squeezing out every last drop of available resources).
But, therefore, you end up with a loop that reads a word (16-bit), writes the lower byte (8-bit), reads the next word, writes the lower byte, etc. Such a loop if it's just doing a memory to memory copy shouldn't actually be any slower once the compiler does it's optimisations, but in the case of writing to a network device … that could well be interpreted by the networking layer as "I want this [1-byte] string content written immediately" (as in, write the character and then do a flush). If that's what's happening, it's probably a case of the Arduino core again, doesn't know what you're doing with that data, so it's just using the standard stream "write a byte" functionality. Which for memory-to-memory is fine, it usually optimises away nice and tight. But if the networking library has a more packet mentality, then it might assume it's being told to send a 1-byte "packet", and goes ahead and does exactly what it's being told to do. I'm really not sure what happens within the networking stuff… This part is mostly just a guess.
In any case, that's also why the Arduino typically copies hard-coded strings into RAM at start-up — it does a single mass PROGMEM to RAM copy loop at the beginning, transferring the entire chunk of string space (not necessarily only strings, either) into regular RAM in one go, so it's all nice and contiguous how you'd expect it to be, and other parts of the code using those strings can then just go ahead and use it like usual (pretty sure RAM is generally a little faster, too). Also, packing the strings would require it to know that it even needs to do that (obviously, not all processors do), and have special handling in the compiler (could probably be handled with some super-fancy core library work in modern compilers, but even then what happens if you tell your compiler to use a prior standard — do you expect it to somehow divide up your code between two different compilers?), etc. So it doesn't.
Do keep in mind Arduino also really isn't targeted at high-end professional embedded systems developers — don't get me wrong, it's awesome, I love it myself, and most of the time it just works (which is more than I can say for some other compilers…), and doesn't cost thousands of dollars. But when you're trying to squeeze that last bit of space or performance out, it doesn't always make the most helpful choices, and can tend to get in the way… Things like digitalWrite() checking that the pin is in the right mode first…
every single time! I really would like a "I know what I'm doing" version…
So yeah, perhaps as suggested already, copy the strings into a RAM buffer, and send from there. Unfortunately, sometimes the networking library will then be super helpful by copying that into yet another buffer — especially if the data is then transmitted by an ISR. In one such case, a networking library expected you to give it a fully formed packet, which it copied into it's private buffer leaving room for the header and footer, then after patching them up, proceeded to dump the buffer to the networking device by ISR. The internal function would then block waiting for the last one to finish, before accepting another write — but since you had to build up each packet as a whole first, it was usually well and truly done by then, and would block on you if it wasn't (you could also check if it was done yet).
Anyhow, I went in and added a stream-based writer directly into the internal buffer starting at the appropriate location (and limiting it to the appropriate length), and split the "send the packet" function to exclude the buffer copy, with the old function now just doing the buffer copy and then calling new library internal function to patch up the header and footer, and begin the sending. Sounds like more work than it actually was, and it all worked beautifully…
But, that was a choice most likely made by the library developer to make it nice and easy for "Arduino type people" to use correctly, and as I say, they explicitly didn't support stream writing specifically to force you to buffer the packet yourself, giving the library time to finish sending the last one in the background, as well as a providing the library with a nice definitive "the data is ready now" signal. In your case, some mixed signals between the Arduino core and the networking library
could conceivably be causing individual characters to be interpreted as entire packets… perhaps… In which case buffering the data yourself will indeed fix that — without going to the lengths that I did.