diff --git a/src/TensorFlow/Build.hs b/src/TensorFlow/Build.hs
--- a/src/TensorFlow/Build.hs
+++ b/src/TensorFlow/Build.hs
@@ -61,12 +61,13 @@
     , withNodeDependencies
     ) where
 
+import Data.ProtoLens.Message(defMessage)
 import Control.Monad.Catch (MonadThrow, MonadCatch, MonadMask)
 import Control.Monad.Fix (MonadFix(..))
 import Control.Monad.IO.Class (MonadIO(..))
+import Control.Monad.Fail (MonadFail(..))
 import Control.Monad.Trans.Class (MonadTrans(..))
 import Control.Monad.Trans.State.Strict(StateT(..), mapStateT, evalStateT)
-import Data.Default (def)
 import Data.Functor.Identity (Identity(..))
 import qualified Data.Map.Strict as Map
 import Data.Monoid ((<>))
@@ -78,13 +79,11 @@
 import Lens.Family2 (Lens', (.~), (^.), (&))
 import Lens.Family2.State.Strict (MonadState, use, uses, (.=), (<>=), (%=))
 import Lens.Family2.Unchecked (lens)
-import Proto.Tensorflow.Core.Framework.Graph
-    ( GraphDef
-    , node
-    )
-import Proto.Tensorflow.Core.Framework.NodeDef
-    ( NodeDef
-    , attr
+import Proto.Tensorflow.Core.Framework.Graph (GraphDef)
+import Proto.Tensorflow.Core.Framework.Graph_Fields (node)
+import Proto.Tensorflow.Core.Framework.NodeDef (NodeDef)
+import Proto.Tensorflow.Core.Framework.NodeDef_Fields
+    ( attr
     , input
     , device
     , name
@@ -193,7 +192,7 @@
 newtype BuildT m a = BuildT (StateT GraphState m a)
     deriving (Functor, Applicative, Monad, MonadIO, MonadTrans,
               MonadState GraphState, MonadThrow, MonadCatch, MonadMask,
-              MonadFix)
+              MonadFix, MonadFail)
 
 -- | An action for building nodes in a TensorFlow graph.
 type Build = BuildT Identity
@@ -238,7 +237,7 @@
 -- | Produce a GraphDef proto representation of the nodes that are rendered in
 -- the given 'Build' action.
 asGraphDef :: Build a -> GraphDef
-asGraphDef b = def & node .~ gs ^. nodeBuffer
+asGraphDef b = defMessage & node .~ gs ^. nodeBuffer
   where
     gs = snd $ runIdentity $ runBuildT b
 
@@ -287,7 +286,7 @@
     let controlInputs
             = map makeDep (o ^. opControlInputs ++ Set.toList controls)
     return $ PendingNode scope (o ^. opName)
-            $ def & op .~ (unOpType (o ^. opType) :: Text)
+            $ defMessage & op .~ (unOpType (o ^. opType) :: Text)
                   & attr .~ _opAttrs o
                   & input .~ (inputs ++ controlInputs)
                   & device .~ dev
diff --git a/src/TensorFlow/Output.hs b/src/TensorFlow/Output.hs
--- a/src/TensorFlow/Output.hs
+++ b/src/TensorFlow/Output.hs
@@ -35,14 +35,14 @@
     , PendingNodeName(..)
     )  where
 
+import Data.ProtoLens.Message(defMessage)
 import qualified Data.Map.Strict as Map
 import Data.String (IsString(..))
 import Data.Text (Text)
 import qualified Data.Text as Text
 import Lens.Family2 (Lens')
 import Lens.Family2.Unchecked (lens)
-import Proto.Tensorflow.Core.Framework.AttrValue (AttrValue(..))
-import Data.Default (def)
+import Proto.Tensorflow.Core.Framework.AttrValue (AttrValue)
 import TensorFlow.Types (Attribute, attrLens)
 
 -- | A type of graph node which has no outputs. These nodes are
@@ -108,7 +108,7 @@
 
 opAttr :: Attribute a => Text -> Lens' OpDef a
 opAttr n = lens _opAttrs (\o x -> o {_opAttrs = x})
-              . lens (Map.findWithDefault def n) (flip (Map.insert n))
+              . lens (Map.findWithDefault defMessage n) (flip (Map.insert n))
               . attrLens
 
 opInputs :: Lens' OpDef [Output]
diff --git a/src/TensorFlow/Session.hs b/src/TensorFlow/Session.hs
--- a/src/TensorFlow/Session.hs
+++ b/src/TensorFlow/Session.hs
@@ -37,7 +37,9 @@
     asyncProdNodes,
     ) where
 
+import Data.ProtoLens.Message(defMessage)
 import Control.Monad (forever, unless, void)
+import Control.Monad.Fail (MonadFail(..))
 import Control.Monad.Catch (MonadThrow, MonadCatch, MonadMask)
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Control.Monad.Trans.Class (MonadTrans, lift)
@@ -50,7 +52,8 @@
 import Data.Text.Encoding (encodeUtf8)
 import Lens.Family2 (Lens', (^.), (&), (.~))
 import Lens.Family2.Unchecked (lens)
-import Proto.Tensorflow.Core.Framework.Graph (GraphDef, node)
+import Proto.Tensorflow.Core.Framework.Graph (GraphDef)
+import Proto.Tensorflow.Core.Framework.Graph_Fields (node)
 import Proto.Tensorflow.Core.Protobuf.Config (ConfigProto)
 import TensorFlow.Build
 import TensorFlow.Nodes
@@ -77,7 +80,7 @@
 newtype SessionT m a
     = Session (ReaderT SessionState (BuildT m) a)
     deriving (Functor, Applicative, Monad, MonadIO, MonadThrow, MonadCatch,
-              MonadMask)
+              MonadMask, MonadFail)
 
 instance MonadTrans SessionT where
   lift = Session . lift . lift
@@ -99,7 +102,7 @@
 instance Default Options where
     def = Options
           { _sessionTarget = ""
-          , _sessionConfig = def
+          , _sessionConfig = defMessage
           , _sessionTracer = const (return ())
           }
 
@@ -141,7 +144,7 @@
     trace <- Session (asks tracer)
     nodesToExtend <- build flushNodeBuffer
     unless (null nodesToExtend) $ liftIO $ do
-        let graphDef = (def :: GraphDef) & node .~ nodesToExtend
+        let graphDef = (defMessage :: GraphDef) & node .~ nodesToExtend
         trace ("Session.extend " <> Builder.string8 (showMessage graphDef))
         FFI.extendGraph session graphDef
     -- Now that all the nodes are created, run the initializers.
diff --git a/src/TensorFlow/Tensor.hs b/src/TensorFlow/Tensor.hs
--- a/src/TensorFlow/Tensor.hs
+++ b/src/TensorFlow/Tensor.hs
@@ -34,7 +34,7 @@
 import Lens.Family2 ((^.))
 import Lens.Family2.State ((%=), use)
 
-import Proto.Tensorflow.Core.Framework.NodeDef (device)
+import Proto.Tensorflow.Core.Framework.NodeDef_Fields (device)
 import TensorFlow.Build
 import TensorFlow.Output (Output, NodeName, outputNodeName, Device(..))
 import TensorFlow.Types
diff --git a/src/TensorFlow/Types.hs b/src/TensorFlow/Types.hs
--- a/src/TensorFlow/Types.hs
+++ b/src/TensorFlow/Types.hs
@@ -64,9 +64,9 @@
     , AllTensorTypes
     ) where
 
+import Data.ProtoLens.Message(defMessage)
 import Data.Functor.Identity (Identity(..))
 import Data.Complex (Complex)
-import Data.Default (def)
 import Data.Int (Int8, Int16, Int32, Int64)
 import Data.Maybe (fromMaybe)
 import Data.Monoid ((<>))
@@ -88,9 +88,11 @@
 import qualified Data.Vector as V
 import qualified Data.Vector.Storable as S
 import Proto.Tensorflow.Core.Framework.AttrValue
-    ( AttrValue(..)
-    , AttrValue'ListValue(..)
-    , b
+    ( AttrValue
+    , AttrValue'ListValue
+    )
+import Proto.Tensorflow.Core.Framework.AttrValue_Fields
+    ( b
     , f
     , i
     , s
@@ -99,11 +101,13 @@
     , shape
     , tensor
     )
+
 import Proto.Tensorflow.Core.Framework.ResourceHandle
     (ResourceHandleProto)
 import Proto.Tensorflow.Core.Framework.Tensor as Tensor
-    ( TensorProto(..)
-    , boolVal
+    (TensorProto)
+import Proto.Tensorflow.Core.Framework.Tensor_Fields as Tensor
+    ( boolVal
     , doubleVal
     , floatVal
     , intVal
@@ -113,9 +117,11 @@
     , uint32Val
     , uint64Val
     )
+
 import Proto.Tensorflow.Core.Framework.TensorShape
-    ( TensorShapeProto(..)
-    , dim
+    (TensorShapeProto)
+import Proto.Tensorflow.Core.Framework.TensorShape_Fields
+    ( dim
     , size
     , unknownRank
     )
@@ -394,7 +400,7 @@
     protoToShape p = fromMaybe (error msg) (view protoMaybeShape p)
       where msg = "Can't convert TensorShapeProto with unknown rank to Shape: "
                   ++ showMessageShort p
-    shapeToProto s' = def & protoMaybeShape .~ Just s'
+    shapeToProto s' = defMessage & protoMaybeShape .~ Just s'
 
 protoMaybeShape :: Lens' TensorShapeProto (Maybe Shape)
 protoMaybeShape = iso protoToShape shapeToProto
@@ -406,9 +412,9 @@
             else Just (Shape (p ^.. dim . traverse . size))
     shapeToProto :: Maybe Shape -> TensorShapeProto
     shapeToProto Nothing =
-        def & unknownRank .~ True
+        defMessage & unknownRank .~ True
     shapeToProto (Just (Shape ds)) =
-        def & dim .~ fmap (\d -> def & size .~ d) ds
+        defMessage & dim .~ fmap (\d -> defMessage & size .~ d) ds
 
 
 class Attribute a where
diff --git a/tensorflow.cabal b/tensorflow.cabal
--- a/tensorflow.cabal
+++ b/tensorflow.cabal
@@ -1,5 +1,5 @@
 name:                tensorflow
-version:             0.2.0.0
+version:             0.2.0.1
 synopsis:            TensorFlow bindings.
 description:
     This library provides an interface to the TensorFlow
@@ -36,7 +36,7 @@
                   , TensorFlow.Types
   other-modules:    TensorFlow.Internal.Raw
   build-tools:      c2hs
-  build-depends:  proto-lens == 0.2.*
+  build-depends:  proto-lens >= 0.4.0 && < 0.6.0
                 , tensorflow-proto == 0.2.*
                 , base >= 4.7 && < 5
                 , async
diff --git a/tests/FFITest.hs b/tests/FFITest.hs
--- a/tests/FFITest.hs
+++ b/tests/FFITest.hs
@@ -22,7 +22,8 @@
 import Test.HUnit (assertBool, assertFailure)
 import Test.Framework (defaultMain)
 import Test.Framework.Providers.HUnit (testCase)
-import Proto.Tensorflow.Core.Framework.OpDef (OpList, op)
+import Proto.Tensorflow.Core.Framework.OpDef (OpList)
+import Proto.Tensorflow.Core.Framework.OpDef_Fields (op)
 
 testParseAll :: IO ()
 testParseAll = do
diff --git a/third_party/tensorflow/c/c_api.h b/third_party/tensorflow/c/c_api.h
--- a/third_party/tensorflow/c/c_api.h
+++ b/third_party/tensorflow/c/c_api.h
@@ -44,6 +44,7 @@
 // * size_t is used to represent byte sizes of objects that are
 //   materialized in the address space of the calling process.
 // * int is used as an index into arrays.
+// * Deletion functions are safe to call on nullptr.
 //
 // Questions left to address:
 // * Might at some point need a way for callers to provide their own Env.
@@ -90,7 +91,7 @@
 // --------------------------------------------------------------------------
 // TF_Version returns a string describing version information of the
 // TensorFlow library. TensorFlow using semantic versioning.
-TF_CAPI_EXPORT extern const char* TF_Version();
+TF_CAPI_EXPORT extern const char* TF_Version(void);
 
 // --------------------------------------------------------------------------
 // TF_DataType holds the type for a scalar value.  E.g., one slot in a tensor.
@@ -156,7 +157,7 @@
 typedef struct TF_Status TF_Status;
 
 // Return a new status object.
-TF_CAPI_EXPORT extern TF_Status* TF_NewStatus();
+TF_CAPI_EXPORT extern TF_Status* TF_NewStatus(void);
 
 // Delete a previously created status object.
 TF_CAPI_EXPORT extern void TF_DeleteStatus(TF_Status*);
@@ -195,7 +196,7 @@
                                                         size_t proto_len);
 
 // Useful for passing *out* a protobuf.
-TF_CAPI_EXPORT extern TF_Buffer* TF_NewBuffer();
+TF_CAPI_EXPORT extern TF_Buffer* TF_NewBuffer(void);
 
 TF_CAPI_EXPORT extern void TF_DeleteBuffer(TF_Buffer*);
 
@@ -304,7 +305,7 @@
 typedef struct TF_SessionOptions TF_SessionOptions;
 
 // Return a new options object.
-TF_CAPI_EXPORT extern TF_SessionOptions* TF_NewSessionOptions();
+TF_CAPI_EXPORT extern TF_SessionOptions* TF_NewSessionOptions(void);
 
 // Set the target in TF_SessionOptions.options.
 // target can be empty, a single entry, or a comma separated list of entries.
@@ -337,7 +338,7 @@
 typedef struct TF_Graph TF_Graph;
 
 // Return a new graph object.
-TF_CAPI_EXPORT extern TF_Graph* TF_NewGraph();
+TF_CAPI_EXPORT extern TF_Graph* TF_NewGraph(void);
 
 // Destroy an options object.  Graph will be deleted once no more
 // TFSession's are referencing it.
@@ -889,15 +890,23 @@
 // TF_GraphImportGraphDef.
 typedef struct TF_ImportGraphDefOptions TF_ImportGraphDefOptions;
 
-TF_CAPI_EXPORT extern TF_ImportGraphDefOptions* TF_NewImportGraphDefOptions();
+TF_CAPI_EXPORT extern TF_ImportGraphDefOptions* TF_NewImportGraphDefOptions(
+    void);
 TF_CAPI_EXPORT extern void TF_DeleteImportGraphDefOptions(
     TF_ImportGraphDefOptions* opts);
 
 // Set the prefix to be prepended to the names of nodes in `graph_def` that will
-// be imported into `graph`.
+// be imported into `graph`. `prefix` is copied and has no lifetime
+// requirements.
 TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetPrefix(
     TF_ImportGraphDefOptions* opts, const char* prefix);
 
+// Set the execution device for nodes in `graph_def`.
+// Only applies to nodes where a device was not already explicitly specified.
+// `device` is copied and has no lifetime requirements.
+TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsSetDefaultDevice(
+    TF_ImportGraphDefOptions* opts, const char* device);
+
 // Set whether to uniquify imported operation names. If true, imported operation
 // names will be modified if their name already exists in the graph. If false,
 // conflicting names will be treated as an error. Note that this option has no
@@ -915,6 +924,7 @@
 // Set any imported nodes with input `src_name:src_index` to have that input
 // replaced with `dst`. `src_name` refers to a node in the graph to be imported,
 // `dst` references a node already existing in the graph being imported into.
+// `src_name` is copied and has no lifetime requirements.
 TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsAddInputMapping(
     TF_ImportGraphDefOptions* opts, const char* src_name, int src_index,
     TF_Output dst);
@@ -922,7 +932,7 @@
 // Set any imported nodes with control input `src_name` to have that input
 // replaced with `dst`. `src_name` refers to a node in the graph to be imported,
 // `dst` references an operation already existing in the graph being imported
-// into.
+// into. `src_name` is copied and has no lifetime requirements.
 TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsRemapControlDependency(
     TF_ImportGraphDefOptions* opts, const char* src_name, TF_Operation* dst);
 
@@ -934,6 +944,7 @@
 // Add an output in `graph_def` to be returned via the `return_outputs` output
 // parameter of TF_GraphImportGraphDef(). If the output is remapped via an input
 // mapping, the corresponding existing tensor in `graph` will be returned.
+// `oper_name` is copied and has no lifetime requirements.
 TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsAddReturnOutput(
     TF_ImportGraphDefOptions* opts, const char* oper_name, int index);
 
@@ -943,7 +954,8 @@
     const TF_ImportGraphDefOptions* opts);
 
 // Add an operation in `graph_def` to be returned via the `return_opers` output
-// parameter of TF_GraphImportGraphDef().
+// parameter of TF_GraphImportGraphDef(). `oper_name` is copied and has no
+// lifetime requirements.
 TF_CAPI_EXPORT extern void TF_ImportGraphDefOptionsAddReturnOperation(
     TF_ImportGraphDefOptions* opts, const char* oper_name);
 
@@ -1126,6 +1138,7 @@
 
 // Adds operations to compute the partial derivatives of sum of `y`s w.r.t `x`s,
 // i.e., d(y_1 + y_2 + ...)/dx_1, d(y_1 + y_2 + ...)/dx_2...
+//
 // `dx` are used as initial gradients (which represent the symbolic partial
 // derivatives of some loss function `L` w.r.t. `y`).
 // `dx` must be nullptr or have size `ny`.
@@ -1134,6 +1147,12 @@
 // The partial derivatives are returned in `dy`. `dy` should be allocated to
 // size `nx`.
 //
+// Gradient nodes are automatically named under the "gradients/" prefix. To
+// guarantee name uniqueness, subsequent calls to the same graph will
+// append an incremental tag to the prefix: "gradients_1/", "gradients_2/", ...
+// See TF_AddGradientsWithPrefix, which provides a means to specify a custom
+// name prefix for operations added to a graph to compute the gradients.
+//
 // WARNING: This function does not yet support all the gradients that python
 // supports. See
 // https://www.tensorflow.org/code/tensorflow/cc/gradients/README.md
@@ -1142,6 +1161,33 @@
                                     TF_Output* x, int nx, TF_Output* dx,
                                     TF_Status* status, TF_Output* dy);
 
+// Adds operations to compute the partial derivatives of sum of `y`s w.r.t `x`s,
+// i.e., d(y_1 + y_2 + ...)/dx_1, d(y_1 + y_2 + ...)/dx_2...
+// This is a variant of TF_AddGradients that allows to caller to pass a custom
+// name prefix to the operations added to a graph to compute the gradients.
+//
+// `dx` are used as initial gradients (which represent the symbolic partial
+// derivatives of some loss function `L` w.r.t. `y`).
+// `dx` must be nullptr or have size `ny`.
+// If `dx` is nullptr, the implementation will use dx of `OnesLike` for all
+// shapes in `y`.
+// The partial derivatives are returned in `dy`. `dy` should be allocated to
+// size `nx`.
+// `prefix` names the scope into which all gradients operations are being added.
+// `prefix` must be unique within the provided graph otherwise this operation
+// will fail. If `prefix` is nullptr, the default prefixing behaviour takes
+// place, see TF_AddGradients for more details.
+//
+// WARNING: This function does not yet support all the gradients that python
+// supports. See
+// https://www.tensorflow.org/code/tensorflow/cc/gradients/README.md
+// for instructions on how to add C++ more gradients.
+TF_CAPI_EXPORT void TF_AddGradientsWithPrefix(TF_Graph* g, const char* prefix,
+                                              TF_Output* y, int ny,
+                                              TF_Output* x, int nx,
+                                              TF_Output* dx, TF_Status* status,
+                                              TF_Output* dy);
+
 // Create a TF_Function from a TF_Graph
 //
 // Params:
@@ -1231,6 +1277,11 @@
     int noutputs, const TF_Output* outputs, const char* const* output_names,
     const TF_FunctionOptions* opts, const char* description, TF_Status* status);
 
+// Returns the name of the graph function.
+// The return value points to memory that is only usable until the next
+// mutation to *func.
+TF_CAPI_EXPORT extern const char* TF_FunctionName(TF_Function* func);
+
 // Write out a serialized representation of `func` (as a FunctionDef protocol
 // message) to `output_func_def` (allocated by TF_NewBuffer()).
 // `output_func_def`'s underlying buffer will be freed when TF_DeleteBuffer()
@@ -1517,6 +1568,13 @@
 TF_CAPI_EXPORT extern int64_t TF_DeviceListMemoryBytes(
     const TF_DeviceList* list, int index, TF_Status* status);
 
+// Retrieve the incarnation number of a given device.
+//
+// If index is out of bounds, an error code will be set in the status object,
+// and 0 will be returned.
+TF_CAPI_EXPORT extern uint64_t TF_DeviceListIncarnation(
+    const TF_DeviceList* list, int index, TF_Status* status);
+
 // --------------------------------------------------------------------------
 // Load plugins containing custom ops and kernels
 
@@ -1554,7 +1612,7 @@
 //
 // The data in the buffer will be the serialized OpList proto for ops registered
 // in this address space.
-TF_CAPI_EXPORT extern TF_Buffer* TF_GetAllOpList();
+TF_CAPI_EXPORT extern TF_Buffer* TF_GetAllOpList(void);
 
 // TF_ApiDefMap encapsulates a collection of API definitions for an operation.
 //
@@ -1598,6 +1656,59 @@
                                                  const char* name,
                                                  size_t name_len,
                                                  TF_Status* status);
+
+// --------------------------------------------------------------------------
+// Kernel definition information.
+
+// Returns a serialized KernelList protocol buffer containing KernelDefs for all
+// registered kernels.
+TF_CAPI_EXPORT extern TF_Buffer* TF_GetAllRegisteredKernels(TF_Status* status);
+
+// Returns a serialized KernelList protocol buffer containing KernelDefs for all
+// kernels registered for the operation named `name`.
+TF_CAPI_EXPORT extern TF_Buffer* TF_GetRegisteredKernelsForOp(
+    const char* name, TF_Status* status);
+
+// --------------------------------------------------------------------------
+// In-process TensorFlow server functionality, for use in distributed training.
+// A Server instance encapsulates a set of devices and a Session target that
+// can participate in distributed training. A server belongs to a cluster
+// (specified by a ClusterSpec), and corresponds to a particular task in a
+// named job. The server can communicate with any other server in the same
+// cluster.
+
+// In-process TensorFlow server.
+typedef struct TF_Server TF_Server;
+
+// Creates a new in-process TensorFlow server configured using a serialized
+// ServerDef protocol buffer provided via `proto` and `proto_len`.
+//
+// The server will not serve any requests until TF_ServerStart is invoked.
+// The server will stop serving requests once TF_ServerStop or
+// TF_DeleteServer is invoked.
+TF_CAPI_EXPORT extern TF_Server* TF_NewServer(const void* proto,
+                                              size_t proto_len,
+                                              TF_Status* status);
+
+// Starts an in-process TensorFlow server.
+TF_CAPI_EXPORT extern void TF_ServerStart(TF_Server* server, TF_Status* status);
+
+// Stops an in-process TensorFlow server.
+TF_CAPI_EXPORT extern void TF_ServerStop(TF_Server* server, TF_Status* status);
+
+// Blocks until the server has been successfully stopped (via TF_ServerStop or
+// TF_ServerClose).
+TF_CAPI_EXPORT extern void TF_ServerJoin(TF_Server* server, TF_Status* status);
+
+// Returns the target string that can be provided to TF_SetTarget() to connect
+// a TF_Session to `server`.
+//
+// The returned string is valid only until TF_DeleteServer is invoked.
+TF_CAPI_EXPORT extern const char* TF_ServerTarget(TF_Server* server);
+
+// Destroy an in-process TensorFlow server, frees memory. If server is running
+// it will be stopped and joined.
+TF_CAPI_EXPORT extern void TF_DeleteServer(TF_Server* server);
 
 #ifdef __cplusplus
 } /* end extern "C" */
