I don't know where it comes from, but it is good advice and fairly straight-forward to understand.
Any sanely designed program will be broken up into various parts, combined and composed in various ways. The harder it is to reason about what any particular part does, the harder it will be to make sure that your program will react in a predictable manner.
Isolating the parts that produce side-effects makes the rest easier to reason about, test, and debug. Reducing the number of side-effects in each part that does generate a side-effect will make that part easier to work with in the same manner.
If you decompose it even further, a return value is an effect. Side-effects are an effect. A function should only produce 1 effect (if possible) because the greater number of inputs and effects a function has, the greater the difficulty in reasoning about what it actually does.