Your last piece of code is almost the definition of a decorator. The only difference is that in the first case, the name decor is evaluated before the function is defined, and in the second, after the function is defined. This only matters if the execution of the function definition changes the name to which it refers.
Undemanding example:
def decor(function): def result(): printf('decorated') return function() return result def plonk(): global decor decor = lambda x: x return None
Now
@decor def my_foo(foo=plonk()): print('my_foo')
differs from
def my_foo(foo=plonk()): print('my_foo') my_foo = decor(my_foo)
source share