implement __repr__ for WorkerContext and others

i agree that it looks nicer. my only concern is that it's more fragile. e.g. `None` will raise attribute error, and while unlikely, if this happens e.g. whilst logging an exception, the original exception info is lost

maybe we could pass values through something like

```
def safe_str/str_for_repr/better_name(value):
    try:
        return value.encode('utf-8')
    except Exception:
        return repr(value)
```