Add new `side_effects` function

Large scale feedback on this would be appreciated.  I suspect that there is probably a better way to accomplish this.

In general the goal is to provide a mechanism to support side effects.  I suspect this is the watered down version of the core idea behind monads.

Mostly I suspect this to be used with debugging, e.g.  

```Python
>>> seq = "Alice", "Bob", "Charlie", ...
>>> seq = side_effects(lambda item: print("working on " + str(item)), seq) 
>>> result = do_work_on(seq)
working on Alice
working on Bob
working on Charlie
...
>>> 
```