Functional programming employs a model of computation called the lambda calculus whereas imperative programming uses the Turing Machine as its model of computation.
Whereas in an imperative language you allocate variables to hold values and then manipulate those values to compute a result (if you know what a Turing Machine is, imagine the head moving back and forth reading and writing values to the tape), with lambda calculus the function forms a boundary around logic. You can only interact with the system by passing values into a function and receiving the output. Therefore a lambda calculus is predictable: given the same input it will always produce the same output. It does not rely on any initial conditions outside of its inputs. It will also not mutate any other logic's state, so it is safe.
Others have already listed out what this means practically for functional programming, so I will leave it here for my explanation.