arm_compute v17.12
diff --git a/examples/SConscript b/examples/SConscript
index 52d2f26..9be9fa9 100644
--- a/examples/SConscript
+++ b/examples/SConscript
@@ -27,6 +27,10 @@
 if env['opencl']:
     Import('opencl')
 
+if env['gles_compute'] and env['os'] != 'android':
+    Import('egl')
+    Import('glesv2')
+
 examples_env = env.Clone()
 
 examples_env.Append(CPPPATH = ["#"])
@@ -56,7 +60,7 @@
         Import('arm_compute_graph_a')
         Import('arm_compute_core_a')
         Import('arm_compute_a')
-        arm_compute_graph_libs = [ arm_compute_graph_a, arm_compute_a, arm_compute_core_a]
+        arm_compute_graph_libs = [ arm_compute_a, arm_compute_core_a, "OpenCL"]
         graph_dependency = arm_compute_graph_a
     else:
         Import('arm_compute_graph_so')
@@ -66,8 +70,14 @@
     graph_utils = examples_env.Object("../utils/GraphUtils.cpp")
     for file in Glob("./graph_*.cpp"):
         example = os.path.basename(os.path.splitext(str(file))[0])
-        prog = examples_env.Program(example, ["{}.cpp".format(example), utils, graph_utils], CPPDEFINES=['ARM_COMPUTE_CL'], LIBS = arm_compute_graph_libs + ["OpenCL"])
-        Depends(prog, [graph_dependency, opencl])
+        prog = None
+        if env['os'] == 'android':
+            prog = examples_env.Program(example, ["{}.cpp".format(example), utils, graph_utils], LIBS = arm_compute_graph_libs + ["OpenCL"], LINKFLAGS=examples_env["LINKFLAGS"]+['-Wl,--whole-archive',graph_dependency,'-Wl,--no-whole-archive'])
+            Depends(prog, [graph_dependency, opencl])
+        else:
+            #-Wl,--allow-shlib-undefined: Ignore dependencies of dependencies
+            prog = examples_env.Program(example, ["{}.cpp".format(example), utils, graph_utils], LIBS = arm_compute_graph_libs, LINKFLAGS=examples_env["LINKFLAGS"]+['-Wl,--allow-shlib-undefined'] )
+            Depends(prog, graph_dependency)
         alias = examples_env.Alias(example, prog)
         Default(alias)
 
@@ -86,3 +96,18 @@
         Depends(prog, arm_compute_dependency)
         alias = examples_env.Alias(example, prog)
         Default(alias)
+
+if env['gles_compute']:
+    for file in Glob("./gc_*.cpp"):
+        example = os.path.basename(os.path.splitext(str(file))[0])
+        if env['os'] != 'android':
+            prog = examples_env.Program(example, ["{}.cpp".format(example), utils], CPPDEFINES=['ARM_COMPUTE_GC'], LIBS = [arm_compute_libs, "EGL", "GLESv2"])
+            Depends(prog, [arm_compute_dependency, egl, glesv2])
+        else:
+            if env['arch'] != 'armv7a':
+                prog = examples_env.Program(example, ["{}.cpp".format(example), utils], CPPDEFINES=['ARM_COMPUTE_GC'], LIBS = [arm_compute_libs, "EGL", "GLESv3"])
+            else:
+                prog = examples_env.Program(example, ["{}.cpp".format(example), utils], CPPDEFINES=['ARM_COMPUTE_GC'], LIBS = [arm_compute_libs, "EGL", "GLESv2"])
+            Depends(prog, [arm_compute_dependency])
+        alias = examples_env.Alias(example, prog)
+        Default(alias)
diff --git a/examples/cl_sgemm.cpp b/examples/cl_sgemm.cpp
new file mode 100644
index 0000000..e1729a8
--- /dev/null
+++ b/examples/cl_sgemm.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef ARM_COMPUTE_CL /* Needed by Utils.cpp to handle OpenCL exceptions properly */
+#error "This example needs to be built with -DARM_COMPUTE_CL"
+#endif /* ARM_COMPUTE_CL */
+
+#include "arm_compute/core/Types.h"
+#include "arm_compute/runtime/CL/CLFunctions.h"
+#include "arm_compute/runtime/CL/CLScheduler.h"
+#include "arm_compute/runtime/CL/CLTuner.h"
+#include "utils/Utils.h"
+
+#include <cstdlib>
+
+using namespace arm_compute;
+using namespace utils;
+
+void main_cl_sgemm(int argc, const char **argv)
+{
+    NPYLoader npy0, npy1, npy2;
+    CLTensor  src0, src1, src2, dst;
+    float     alpha = 1.0f, beta = 0.0f;
+
+    CLTuner tuner;
+    CLScheduler::get().default_init(&tuner);
+
+    std::ifstream stream;
+    if(argc > 1)
+    {
+        stream.open(argv[1], std::fstream::in);
+    }
+
+    if(argc < 3 || (argc < 4 && stream.bad()))
+    {
+        // Print help
+        std::cout << "Usage: 1) ./build/cl_sgemm input_matrix_1.npy input_matrix_2.npy [input_matrix_3.npy] [alpha = 1] [beta = 0]\n";
+        std::cout << "       2) ./build/cl_sgemm M N K [alpha = 1.0f] [beta = 0.0f]\n\n";
+        std::cout << "Too few or no input_matrices provided. Using M=7, N=3, K=5, alpha=1.0f and beta=0.0f\n\n";
+
+        src0.allocator()->init(TensorInfo(TensorShape(5U, 7U), 1, DataType::F32));
+        src1.allocator()->init(TensorInfo(TensorShape(3U, 5U), 1, DataType::F32));
+        src2.allocator()->init(TensorInfo(TensorShape(3U, 7U), 1, DataType::F32));
+    }
+    else
+    {
+        if(stream.good()) /* case file1.npy file2.npy [file3.npy] [alpha = 1.0f] [beta = 0.0f] */
+        {
+            npy0.open(argv[1]);
+            npy0.init_tensor(src0, DataType::F32);
+            npy1.open(argv[2]);
+            npy1.init_tensor(src1, DataType::F32);
+
+            if(argc > 3)
+            {
+                stream.close();
+                stream.clear();
+                stream.open(argv[3], std::fstream::in);
+                if(stream.good()) /* case with third file */
+                {
+                    npy2.open(argv[3]);
+                    npy2.init_tensor(src2, DataType::F32);
+
+                    if(argc > 4)
+                    {
+                        // Convert string to float
+                        alpha = strtof(argv[4], nullptr);
+
+                        if(argc > 5)
+                        {
+                            // Convert string to float
+                            beta = strtof(argv[5], nullptr);
+                        }
+                    }
+                }
+                else /* case without third file */
+                {
+                    alpha = strtof(argv[3], nullptr);
+
+                    if(argc > 4)
+                    {
+                        beta = strtof(argv[4], nullptr);
+                    }
+                }
+            }
+        }
+        else /* case M N K [alpha = 1.0f] [beta = 0.0f] */
+        {
+            size_t M = strtol(argv[1], nullptr, 10);
+            size_t N = strtol(argv[2], nullptr, 10);
+            size_t K = strtol(argv[3], nullptr, 10);
+
+            src0.allocator()->init(TensorInfo(TensorShape(K, M), 1, DataType::F32));
+            src1.allocator()->init(TensorInfo(TensorShape(N, K), 1, DataType::F32));
+            src2.allocator()->init(TensorInfo(TensorShape(N, M), 1, DataType::F32));
+
+            if(argc > 4)
+            {
+                alpha = strtof(argv[4], nullptr);
+
+                if(argc > 5)
+                {
+                    beta = strtof(argv[5], nullptr);
+                }
+            }
+        }
+    }
+
+    init_sgemm_output(dst, src0, src1, DataType::F32);
+
+    // Configure function
+    CLGEMM sgemm;
+    sgemm.configure(&src0, &src1, (src2.info()->total_size() > 0) ? &src2 : nullptr, &dst, alpha, beta);
+
+    // Allocate all the images
+    src0.allocator()->allocate();
+    src1.allocator()->allocate();
+    dst.allocator()->allocate();
+
+    // Fill the input images with either the data provided or random data
+    if(npy0.is_open())
+    {
+        npy0.fill_tensor(src0);
+        npy1.fill_tensor(src1);
+
+        if(npy2.is_open())
+        {
+            src2.allocator()->allocate();
+            npy2.fill_tensor(src2);
+        }
+    }
+    else
+    {
+        src2.allocator()->allocate();
+
+        fill_random_tensor(src0, -1.f, 1.f);
+        fill_random_tensor(src1, -1.f, 1.f);
+        fill_random_tensor(src2, -1.f, 1.f);
+    }
+
+    // Dummy run for CLTuner
+    sgemm.run();
+
+    auto start = std::chrono::high_resolution_clock::now();
+
+    // Execute the function
+    sgemm.run();
+
+    // Make sure all the OpenCL jobs are done executing:
+    CLScheduler::get().sync();
+
+    auto stop = std::chrono::high_resolution_clock::now();
+
+    if(!npy0.is_open()) /* If the inputs were not files, print the results */
+    {
+        std::cout << "\nMatrix 1:" << std::endl;
+        src0.map(true);
+        src0.print(std::cout, IOFormatInfo());
+        src0.unmap();
+
+        std::cout << "Matrix 2:" << std::endl;
+        src1.map(true);
+        src1.print(std::cout, IOFormatInfo());
+        src1.unmap();
+
+        std::cout << "Matrix 3:" << std::endl;
+        src2.map(true);
+        src2.print(std::cout, IOFormatInfo());
+        src2.unmap();
+
+        std::cout << "Alpha:" << alpha << "\n\n";
+        std::cout << "Beta:" << beta << "\n\n";
+
+        std::cout << "Output Matrix:" << std::endl;
+        dst.map(true);
+        dst.print(std::cout, IOFormatInfo());
+        dst.unmap();
+    }
+    else /* Save to .npy file */
+    {
+        save_to_npy(dst, "sgemm_out.npy", npy0.is_fortran());
+    }
+
+    auto delta = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
+    std::cout << "Time elapsed: " << delta.count() << "us." << std::endl;
+}
+
+/** Main program for sgemm test
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Matrix A, [optional] Matrix B, [optional] Matrix C, [optional] alpha, [optional] beta )
+ */
+int main(int argc, const char **argv)
+{
+    return utils::run_example(argc, argv, main_cl_sgemm);
+}
diff --git a/examples/gc_absdiff.cpp b/examples/gc_absdiff.cpp
new file mode 100644
index 0000000..cd3e429
--- /dev/null
+++ b/examples/gc_absdiff.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef ARM_COMPUTE_GC /* Needed by Utils.cpp to handle OpenGL ES exceptions properly */
+#error "This example needs to be built with -DARM_COMPUTE_GC"
+#endif /* ARM_COMPUTE_GC */
+
+#include "arm_compute/core/Types.h"
+#include "arm_compute/runtime/GLES_COMPUTE/GCFunctions.h"
+#include "arm_compute/runtime/GLES_COMPUTE/GCScheduler.h"
+#include "utils/Utils.h"
+
+using namespace arm_compute;
+using namespace utils;
+
+void main_gc_absdiff(int argc, const char **argv)
+{
+    PPMLoader ppm1, ppm2;
+    GCImage   src1, src2, dst;
+    GCScheduler::get().default_init();
+    if(argc < 2)
+    {
+        // Print help
+        std::cout << "Usage: " << argv[0] << " [input0_image.ppm] [input1_image.ppm] \n\n";
+        std::cout << "No input_image provided, creating two dummy 640x480 images\n";
+        // Create two empty grayscale 640x480 images
+        src1.allocator()->init(TensorInfo(640, 480, Format::U8));
+        src2.allocator()->init(TensorInfo(640, 480, Format::U8));
+    }
+    else if(argc < 3)
+    {
+        // Print help
+        std::cout << "Usage: " << argv[0] << " [input0_image.ppm] [input1_image.ppm] \n\n";
+        std::cout << "Only one input_image provided, creating a dummy 640x480 image\n";
+        ppm1.open(argv[1]);
+        ppm1.init_image(src1, Format::U8);
+        // Create an empty grayscale 640x480 image
+        src2.allocator()->init(TensorInfo(640, 480, Format::U8));
+    }
+    else
+    {
+        ppm1.open(argv[1]);
+        ppm1.init_image(src1, Format::U8);
+        ppm2.open(argv[2]);
+        ppm2.init_image(src2, Format::U8);
+    }
+
+    // Configure the temporary and destination images
+    dst.allocator()->init(*src1.info());
+
+    GCAbsoluteDifference absdiff;
+    absdiff.configure(&src1, &src2, &dst);
+
+    // Allocate all the images
+    src1.allocator()->allocate();
+    src2.allocator()->allocate();
+    dst.allocator()->allocate();
+
+    // Fill the input image with the content of the PPM image if a filename was provided:
+    if(ppm1.is_open())
+    {
+        ppm1.fill_image(src1);
+    }
+    if(ppm2.is_open())
+    {
+        ppm2.fill_image(src2);
+    }
+
+    // Execute the functions:
+    absdiff.run();
+
+    // Make sure all the jobs are done executing:
+    GCScheduler::get().sync();
+
+    // Save the result to file:
+    if(ppm1.is_open())
+    {
+        const std::string output_filename = std::string(argv[1]) + "_out.ppm";
+        save_to_ppm(dst, output_filename); // save_to_ppm maps and unmaps the image to store as PPM
+    }
+}
+
+/** Main program for absdiff test
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Path to the first PPM image to process, [optional] Path the the second PPM image to process )
+ */
+int main(int argc, const char **argv)
+{
+    return utils::run_example(argc, argv, main_gc_absdiff);
+}
diff --git a/examples/graph_alexnet.cpp b/examples/graph_alexnet.cpp
index bb5905e..0d5531f 100644
--- a/examples/graph_alexnet.cpp
+++ b/examples/graph_alexnet.cpp
@@ -21,16 +21,8 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#ifndef ARM_COMPUTE_CL /* Needed by Utils.cpp to handle OpenCL exceptions properly */
-#error "This example needs to be built with -DARM_COMPUTE_CL"
-#endif /* ARM_COMPUTE_CL */
-
-#include "arm_compute/core/Logger.h"
 #include "arm_compute/graph/Graph.h"
 #include "arm_compute/graph/Nodes.h"
-#include "arm_compute/runtime/CL/CLScheduler.h"
-#include "arm_compute/runtime/CPP/CPPScheduler.h"
-#include "arm_compute/runtime/Scheduler.h"
 #include "support/ToolchainSupport.h"
 #include "utils/GraphUtils.h"
 #include "utils/Utils.h"
@@ -42,76 +34,10 @@
 using namespace arm_compute::graph;
 using namespace arm_compute::graph_utils;
 
-/** Generates appropriate accessor according to the specified path
- *
- * @note If path is empty will generate a DummyAccessor else will generate a NumPyBinLoader
- *
- * @param[in] path      Path to the data files
- * @param[in] data_file Relative path to the data files from path
- *
- * @return An appropriate tensor accessor
- */
-std::unique_ptr<ITensorAccessor> get_accessor(const std::string &path, const std::string &data_file)
-{
-    if(path.empty())
-    {
-        return arm_compute::support::cpp14::make_unique<DummyAccessor>();
-    }
-    else
-    {
-        return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(path + data_file);
-    }
-}
-
-/** Generates appropriate input accessor according to the specified ppm_path
- *
- * @note If ppm_path is empty will generate a DummyAccessor else will generate a PPMAccessor
- *
- * @param[in] ppm_path Path to PPM file
- * @param[in] mean_r   Red mean value to be subtracted from red channel
- * @param[in] mean_g   Green mean value to be subtracted from green channel
- * @param[in] mean_b   Blue mean value to be subtracted from blue channel
- *
- * @return An appropriate tensor accessor
- */
-std::unique_ptr<ITensorAccessor> get_input_accessor(const std::string &ppm_path, float mean_r, float mean_g, float mean_b)
-{
-    if(ppm_path.empty())
-    {
-        return arm_compute::support::cpp14::make_unique<DummyAccessor>();
-    }
-    else
-    {
-        return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, true, mean_r, mean_g, mean_b);
-    }
-}
-
-/** Generates appropriate output accessor according to the specified labels_path
- *
- * @note If labels_path is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
- *
- * @param[in]  labels_path   Path to labels text file
- * @param[in]  top_n         (Optional) Number of output classes to print
- * @param[out] output_stream (Optional) Output stream
- *
- * @return An appropriate tensor accessor
- */
-std::unique_ptr<ITensorAccessor> get_output_accessor(const std::string &labels_path, size_t top_n = 5, std::ostream &output_stream = std::cout)
-{
-    if(labels_path.empty())
-    {
-        return arm_compute::support::cpp14::make_unique<DummyAccessor>();
-    }
-    else
-    {
-        return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(labels_path, top_n, output_stream);
-    }
-}
-
 /** Example demonstrating how to implement AlexNet's network using the Compute Library's graph API
  *
  * @param[in] argc Number of arguments
- * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] image, [optional] labels )
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
  */
 void main_graph_alexnet(int argc, const char **argv)
 {
@@ -123,62 +49,62 @@
     constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
     constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
 
+    // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+    TargetHint            target_hint      = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+    ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
+
     // Parse arguments
     if(argc < 2)
     {
         // Print help
-        std::cout << "Usage: " << argv[0] << " [path_to_data] [image] [labels]\n\n";
+        std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
         std::cout << "No data folder provided: using random values\n\n";
     }
     else if(argc == 2)
     {
-        data_path = argv[1];
-        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [image] [labels]\n\n";
-        std::cout << "No image provided: using random values\n\n";
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
     }
     else if(argc == 3)
     {
-        data_path = argv[1];
-        image     = argv[2];
-        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [labels]\n\n";
+        data_path = argv[2];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+        std::cout << "No image provided: using random values\n\n";
+    }
+    else if(argc == 4)
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
         std::cout << "No text file with labels provided: skipping output accessor\n\n";
     }
     else
     {
-        data_path = argv[1];
-        image     = argv[2];
-        label     = argv[3];
-    }
-
-    // Check if OpenCL is available and initialize the scheduler
-    TargetHint hint = TargetHint::NEON;
-    if(arm_compute::opencl_is_available())
-    {
-        arm_compute::CLScheduler::get().default_init();
-        hint = TargetHint::OPENCL;
+        data_path = argv[2];
+        image     = argv[3];
+        label     = argv[4];
     }
 
     Graph graph;
-    arm_compute::Logger::get().set_logger(std::cout, arm_compute::LoggerVerbosity::INFO);
 
-    graph << hint
+    graph << target_hint
           << Tensor(TensorInfo(TensorShape(227U, 227U, 3U, 1U), 1, DataType::F32),
                     get_input_accessor(image, mean_r, mean_g, mean_b))
           // Layer 1
           << ConvolutionLayer(
               11U, 11U, 96U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv1_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv1_b.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv1_b.npy"),
               PadStrideInfo(4, 4, 0, 0))
           << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
           << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
           << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
           // Layer 2
-          << ConvolutionMethodHint::DIRECT
+          << convolution_hint
           << ConvolutionLayer(
               5U, 5U, 256U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv2_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv2_b.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv2_b.npy"),
               PadStrideInfo(1, 1, 2, 2), 2)
           << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
           << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
@@ -186,42 +112,42 @@
           // Layer 3
           << ConvolutionLayer(
               3U, 3U, 384U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv3_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv3_b.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv3_b.npy"),
               PadStrideInfo(1, 1, 1, 1))
           << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
           // Layer 4
           << ConvolutionLayer(
               3U, 3U, 384U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv4_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv4_b.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv4_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv4_b.npy"),
               PadStrideInfo(1, 1, 1, 1), 2)
           << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
           // Layer 5
           << ConvolutionLayer(
               3U, 3U, 256U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv5_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/conv5_b.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv5_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/conv5_b.npy"),
               PadStrideInfo(1, 1, 1, 1), 2)
           << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
           << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0)))
           // Layer 6
           << FullyConnectedLayer(
               4096U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/fc6_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/fc6_b.npy"))
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc6_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc6_b.npy"))
           << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
           // Layer 7
           << FullyConnectedLayer(
               4096U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/fc7_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/fc7_b.npy"))
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc7_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc7_b.npy"))
           << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
           // Layer 8
           << FullyConnectedLayer(
               1000U,
-              get_accessor(data_path, "/cnn_data/alexnet_model/fc8_w.npy"),
-              get_accessor(data_path, "/cnn_data/alexnet_model/fc8_b.npy"))
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc8_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/alexnet_model/fc8_b.npy"))
           // Softmax
           << SoftmaxLayer()
           << Tensor(get_output_accessor(label, 5));
@@ -233,7 +159,7 @@
 /** Main program for AlexNet
  *
  * @param[in] argc Number of arguments
- * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] image, [optional] labels )
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
  */
 int main(int argc, const char **argv)
 {
diff --git a/examples/graph_googlenet.cpp b/examples/graph_googlenet.cpp
new file mode 100644
index 0000000..d08382a
--- /dev/null
+++ b/examples/graph_googlenet.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/graph/Graph.h"
+#include "arm_compute/graph/Nodes.h"
+#include "arm_compute/graph/SubGraph.h"
+#include "support/ToolchainSupport.h"
+#include "utils/GraphUtils.h"
+#include "utils/Utils.h"
+
+#include <cstdlib>
+#include <tuple>
+
+using namespace arm_compute::graph;
+using namespace arm_compute::graph_utils;
+
+namespace
+{
+BranchLayer get_inception_node(const std::string &data_path, std::string &&param_path,
+                               unsigned int a_filt,
+                               std::tuple<unsigned int, unsigned int> b_filters,
+                               std::tuple<unsigned int, unsigned int> c_filters,
+                               unsigned int d_filt)
+{
+    std::string total_path = "/cnn_data/googlenet_model/" + param_path + "/" + param_path + "_";
+    SubGraph    i_a;
+    i_a << ConvolutionLayer(
+            1U, 1U, a_filt,
+            get_weights_accessor(data_path, total_path + "1x1_w.npy"),
+            get_weights_accessor(data_path, total_path + "1x1_b.npy"),
+            PadStrideInfo(1, 1, 0, 0))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+    SubGraph i_b;
+    i_b << ConvolutionLayer(
+            1U, 1U, std::get<0>(b_filters),
+            get_weights_accessor(data_path, total_path + "3x3_reduce_w.npy"),
+            get_weights_accessor(data_path, total_path + "3x3_reduce_b.npy"),
+            PadStrideInfo(1, 1, 0, 0))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+        << ConvolutionLayer(
+            3U, 3U, std::get<1>(b_filters),
+            get_weights_accessor(data_path, total_path + "3x3_w.npy"),
+            get_weights_accessor(data_path, total_path + "3x3_b.npy"),
+            PadStrideInfo(1, 1, 1, 1))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+    SubGraph i_c;
+    i_c << ConvolutionLayer(
+            1U, 1U, std::get<0>(c_filters),
+            get_weights_accessor(data_path, total_path + "5x5_reduce_w.npy"),
+            get_weights_accessor(data_path, total_path + "5x5_reduce_b.npy"),
+            PadStrideInfo(1, 1, 0, 0))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+        << ConvolutionLayer(
+            5U, 5U, std::get<1>(c_filters),
+            get_weights_accessor(data_path, total_path + "5x5_w.npy"),
+            get_weights_accessor(data_path, total_path + "5x5_b.npy"),
+            PadStrideInfo(1, 1, 2, 2))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+    SubGraph i_d;
+    i_d << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(1, 1, 1, 1, DimensionRoundingType::CEIL)))
+        << ConvolutionLayer(
+            1U, 1U, d_filt,
+            get_weights_accessor(data_path, total_path + "pool_proj_w.npy"),
+            get_weights_accessor(data_path, total_path + "pool_proj_b.npy"),
+            PadStrideInfo(1, 1, 0, 0))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+    return BranchLayer(BranchMergeMethod::DEPTH_CONCATENATE, std::move(i_a), std::move(i_b), std::move(i_c), std::move(i_d));
+}
+} // namespace
+
+/** Example demonstrating how to implement Googlenet's network using the Compute Library's graph API
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+void main_graph_googlenet(int argc, const char **argv)
+{
+    std::string data_path; /* Path to the trainable data */
+    std::string image;     /* Image data */
+    std::string label;     /* Label data */
+
+    constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
+    constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
+    constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
+
+    // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+    TargetHint            target_hint      = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+    ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
+
+    // Parse arguments
+    if(argc < 2)
+    {
+        // Print help
+        std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 2)
+    {
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 3)
+    {
+        data_path = argv[2];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+        std::cout << "No image provided: using random values\n\n";
+    }
+    else if(argc == 4)
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+        std::cout << "No text file with labels provided: skipping output accessor\n\n";
+    }
+    else
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        label     = argv[4];
+    }
+
+    Graph graph;
+
+    graph << target_hint
+          << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+                    get_input_accessor(image, mean_r, mean_g, mean_b))
+          << ConvolutionLayer(
+              7U, 7U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv1/conv1_7x7_s2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv1/conv1_7x7_s2_b.npy"),
+              PadStrideInfo(2, 2, 3, 3))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+          << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
+          << convolution_hint
+          << ConvolutionLayer(
+              1U, 1U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_reduce_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_reduce_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 192U,
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/conv2/conv2_3x3_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << NormalizationLayer(NormalizationLayerInfo(NormType::CROSS_MAP, 5, 0.0001f, 0.75f))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+          << get_inception_node(data_path, "inception_3a", 64, std::make_tuple(96U, 128U), std::make_tuple(16U, 32U), 32U)
+          << get_inception_node(data_path, "inception_3b", 128, std::make_tuple(128U, 192U), std::make_tuple(32U, 96U), 64U)
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+          << get_inception_node(data_path, "inception_4a", 192, std::make_tuple(96U, 208U), std::make_tuple(16U, 48U), 64U)
+          << get_inception_node(data_path, "inception_4b", 160, std::make_tuple(112U, 224U), std::make_tuple(24U, 64U), 64U)
+          << get_inception_node(data_path, "inception_4c", 128, std::make_tuple(128U, 256U), std::make_tuple(24U, 64U), 64U)
+          << get_inception_node(data_path, "inception_4d", 112, std::make_tuple(144U, 288U), std::make_tuple(32U, 64U), 64U)
+          << get_inception_node(data_path, "inception_4e", 256, std::make_tuple(160U, 320U), std::make_tuple(32U, 128U), 128U)
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+          << get_inception_node(data_path, "inception_5a", 256, std::make_tuple(160U, 320U), std::make_tuple(32U, 128U), 128U)
+          << get_inception_node(data_path, "inception_5b", 384, std::make_tuple(192U, 384U), std::make_tuple(48U, 128U), 128U)
+          << PoolingLayer(PoolingLayerInfo(PoolingType::AVG, 7, PadStrideInfo(1, 1, 0, 0, DimensionRoundingType::CEIL)))
+          << FullyConnectedLayer(
+              1000U,
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/loss3/loss3_classifier_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/googlenet_model/loss3/loss3_classifier_b.npy"))
+          << SoftmaxLayer()
+          << Tensor(get_output_accessor(label, 5));
+
+    graph.run();
+}
+
+/** Main program for Googlenet
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+int main(int argc, const char **argv)
+{
+    return arm_compute::utils::run_example(argc, argv, main_graph_googlenet);
+}
diff --git a/examples/graph_lenet.cpp b/examples/graph_lenet.cpp
index 1427abe..d4a4438 100644
--- a/examples/graph_lenet.cpp
+++ b/examples/graph_lenet.cpp
@@ -21,26 +21,19 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#ifndef ARM_COMPUTE_CL /* Needed by Utils.cpp to handle OpenCL exceptions properly */
-#error "This example needs to be built with -DARM_COMPUTE_CL"
-#endif /* ARM_COMPUTE_CL */
-
-#include "arm_compute/core/Logger.h"
 #include "arm_compute/graph/Graph.h"
 #include "arm_compute/graph/Nodes.h"
-#include "arm_compute/runtime/CL/CLScheduler.h"
-#include "arm_compute/runtime/Scheduler.h"
 #include "support/ToolchainSupport.h"
 #include "utils/GraphUtils.h"
 #include "utils/Utils.h"
 
 #include <cstdlib>
-#include <iostream>
-#include <memory>
 
 using namespace arm_compute::graph;
 using namespace arm_compute::graph_utils;
 
+namespace
+{
 /** Generates appropriate accessor according to the specified path
  *
  * @note If path is empty will generate a DummyAccessor else will generate a NumPyBinLoader
@@ -61,51 +54,51 @@
         return arm_compute::support::cpp14::make_unique<NumPyBinLoader>(path + data_file);
     }
 }
+} // namespace
 
 /** Example demonstrating how to implement LeNet's network using the Compute Library's graph API
  *
  * @param[in] argc Number of arguments
- * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] batches )
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] batches )
  */
 void main_graph_lenet(int argc, const char **argv)
 {
     std::string  data_path;   /** Path to the trainable data */
     unsigned int batches = 4; /** Number of batches */
 
+    // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+    TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+
     // Parse arguments
     if(argc < 2)
     {
         // Print help
-        std::cout << "Usage: " << argv[0] << " [path_to_data] [batches]\n\n";
+        std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [batches]\n\n";
         std::cout << "No data folder provided: using random values\n\n";
     }
     else if(argc == 2)
     {
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [batches]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 3)
+    {
         //Do something with argv[1]
-        data_path = argv[1];
+        data_path = argv[2];
         std::cout << "Usage: " << argv[0] << " [path_to_data] [batches]\n\n";
         std::cout << "No number of batches where specified, thus will use the default : " << batches << "\n\n";
     }
     else
     {
         //Do something with argv[1] and argv[2]
-        data_path = argv[1];
-        batches   = std::strtol(argv[2], nullptr, 0);
-    }
-
-    // Check if OpenCL is available and initialize the scheduler
-    TargetHint hint = TargetHint::NEON;
-    if(arm_compute::opencl_is_available())
-    {
-        arm_compute::CLScheduler::get().default_init();
-        hint = TargetHint::OPENCL;
+        data_path = argv[2];
+        batches   = std::strtol(argv[3], nullptr, 0);
     }
 
     Graph graph;
-    arm_compute::Logger::get().set_logger(std::cout, arm_compute::LoggerVerbosity::INFO);
 
     //conv1 << pool1 << conv2 << pool2 << fc1 << act1 << fc2 << smx
-    graph << hint
+    graph << target_hint
           << Tensor(TensorInfo(TensorShape(28U, 28U, 1U, batches), 1, DataType::F32), DummyAccessor())
           << ConvolutionLayer(
               5U, 5U, 20U,
@@ -137,7 +130,7 @@
 /** Main program for LeNet
  *
  * @param[in] argc Number of arguments
- * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] batches )
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] batches )
  */
 int main(int argc, const char **argv)
 {
diff --git a/examples/graph_mobilenet.cpp b/examples/graph_mobilenet.cpp
new file mode 100644
index 0000000..0c916c7
--- /dev/null
+++ b/examples/graph_mobilenet.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/graph/Graph.h"
+#include "arm_compute/graph/Nodes.h"
+#include "support/ToolchainSupport.h"
+#include "utils/GraphUtils.h"
+#include "utils/Utils.h"
+
+#include <cstdlib>
+
+using namespace arm_compute::graph;
+using namespace arm_compute::graph_utils;
+
+namespace
+{
+BranchLayer get_dwsc_node(const std::string &data_path, std::string &&param_path,
+                          unsigned int  conv_filt,
+                          PadStrideInfo dwc_pad_stride_info, PadStrideInfo conv_pad_stride_info)
+{
+    std::string total_path = "/cnn_data/mobilenet_v1_model/" + param_path + "_";
+    SubGraph    sg;
+    sg << DepthwiseConvolutionLayer(
+           3U, 3U,
+           get_weights_accessor(data_path, total_path + "depthwise_depthwise_weights.npy"),
+           std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
+           dwc_pad_stride_info,
+           true)
+       << BatchNormalizationLayer(
+           get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_moving_mean.npy"),
+           get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_moving_variance.npy"),
+           get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_beta.npy"),
+           get_weights_accessor(data_path, total_path + "depthwise_BatchNorm_gamma.npy"),
+           0.001f)
+       << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f))
+       << ConvolutionLayer(
+           1U, 1U, conv_filt,
+           get_weights_accessor(data_path, total_path + "pointwise_weights.npy"),
+           std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
+           conv_pad_stride_info)
+       << BatchNormalizationLayer(
+           get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_moving_mean.npy"),
+           get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_moving_variance.npy"),
+           get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_beta.npy"),
+           get_weights_accessor(data_path, total_path + "pointwise_BatchNorm_gamma.npy"),
+           0.001f)
+       << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f));
+
+    return BranchLayer(std::move(sg));
+}
+} // namespace
+
+/** Example demonstrating how to implement MobileNet's network using the Compute Library's graph API
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+void main_graph_mobilenet(int argc, const char **argv)
+{
+    std::string data_path; /* Path to the trainable data */
+    std::string image;     /* Image data */
+    std::string label;     /* Label data */
+
+    constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
+    constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
+    constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
+
+    // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+    TargetHint target_hint = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+
+    // Parse arguments
+    if(argc < 2)
+    {
+        // Print help
+        std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 2)
+    {
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 3)
+    {
+        data_path = argv[2];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+        std::cout << "No image provided: using random values\n\n";
+    }
+    else if(argc == 4)
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+        std::cout << "No text file with labels provided: skipping output accessor\n\n";
+    }
+    else
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        label     = argv[4];
+    }
+
+    Graph graph;
+
+    graph << target_hint
+          << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+                    get_input_accessor(image, mean_r, mean_g, mean_b))
+          << ConvolutionLayer(
+              3U, 3U, 32U,
+              get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_weights.npy"),
+              std::unique_ptr<arm_compute::graph::ITensorAccessor>(nullptr),
+              PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR))
+          << BatchNormalizationLayer(
+              get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_moving_mean.npy"),
+              get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_moving_variance.npy"),
+              get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_beta.npy"),
+              get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Conv2d_0_BatchNorm_gamma.npy"),
+              0.001f)
+
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::BOUNDED_RELU, 6.f))
+          << get_dwsc_node(data_path, "Conv2d_1", 64, PadStrideInfo(1, 1, 1, 1), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_2", 128, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_3", 128, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_4", 256, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_5", 256, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_6", 512, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_7", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_8", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_9", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_10", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_11", 512, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_12", 1024, PadStrideInfo(2, 2, 0, 1, 0, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << get_dwsc_node(data_path, "Conv2d_13", 1024, PadStrideInfo(1, 1, 1, 1, 1, 1, DimensionRoundingType::FLOOR), PadStrideInfo(1, 1, 0, 0))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::AVG))
+          << ConvolutionLayer(
+              1U, 1U, 1001U,
+              get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Logits_Conv2d_1c_1x1_weights.npy"),
+              get_weights_accessor(data_path, "/cnn_data/mobilenet_v1_model/Logits_Conv2d_1c_1x1_biases.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ReshapeLayer(TensorShape(1001U))
+          << SoftmaxLayer()
+          << Tensor(get_output_accessor(label, 5));
+
+    graph.run();
+}
+
+/** Main program for MobileNetV1
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+int main(int argc, const char **argv)
+{
+    return arm_compute::utils::run_example(argc, argv, main_graph_mobilenet);
+}
diff --git a/examples/graph_squeezenet.cpp b/examples/graph_squeezenet.cpp
new file mode 100644
index 0000000..c8c411a
--- /dev/null
+++ b/examples/graph_squeezenet.cpp
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/graph/Graph.h"
+#include "arm_compute/graph/Nodes.h"
+#include "arm_compute/graph/SubGraph.h"
+#include "support/ToolchainSupport.h"
+#include "utils/GraphUtils.h"
+#include "utils/Utils.h"
+
+#include <cstdlib>
+#include <tuple>
+
+using namespace arm_compute::graph;
+using namespace arm_compute::graph_utils;
+using namespace arm_compute::logging;
+
+namespace
+{
+BranchLayer get_expand_fire_node(const std::string &data_path, std::string &&param_path, unsigned int expand1_filt, unsigned int expand3_filt)
+{
+    std::string total_path = "/cnn_data/squeezenet_v1.0_model/" + param_path + "_";
+    SubGraph    i_a;
+    i_a << ConvolutionLayer(
+            1U, 1U, expand1_filt,
+            get_weights_accessor(data_path, total_path + "expand1x1_w.npy"),
+            get_weights_accessor(data_path, total_path + "expand1x1_b.npy"),
+            PadStrideInfo(1, 1, 0, 0))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+    SubGraph i_b;
+    i_b << ConvolutionLayer(
+            3U, 3U, expand3_filt,
+            get_weights_accessor(data_path, total_path + "expand3x3_w.npy"),
+            get_weights_accessor(data_path, total_path + "expand3x3_b.npy"),
+            PadStrideInfo(1, 1, 1, 1))
+        << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU));
+
+    return BranchLayer(BranchMergeMethod::DEPTH_CONCATENATE, std::move(i_a), std::move(i_b));
+}
+} // namespace
+
+/** Example demonstrating how to implement Squeezenet's network using the Compute Library's graph API
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+void main_graph_squeezenet(int argc, const char **argv)
+{
+    std::string data_path; /* Path to the trainable data */
+    std::string image;     /* Image data */
+    std::string label;     /* Label data */
+
+    constexpr float mean_r = 122.68f; /* Mean value to subtract from red channel */
+    constexpr float mean_g = 116.67f; /* Mean value to subtract from green channel */
+    constexpr float mean_b = 104.01f; /* Mean value to subtract from blue channel */
+
+    // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+    TargetHint            target_hint      = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+    ConvolutionMethodHint convolution_hint = target_hint == TargetHint::NEON ? ConvolutionMethodHint::GEMM : ConvolutionMethodHint::DIRECT;
+
+    // Parse arguments
+    if(argc < 2)
+    {
+        // Print help
+        std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 2)
+    {
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 3)
+    {
+        data_path = argv[2];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+        std::cout << "No image provided: using random values\n\n";
+    }
+    else if(argc == 4)
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+        std::cout << "No text file with labels provided: skipping output accessor\n\n";
+    }
+    else
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        label     = argv[4];
+    }
+
+    Graph graph;
+
+    graph << target_hint
+          << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+                    get_input_accessor(image, mean_r, mean_g, mean_b))
+          << ConvolutionLayer(
+              7U, 7U, 96U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv1_b.npy"),
+              PadStrideInfo(2, 2, 0, 0))
+          << convolution_hint
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+          << ConvolutionLayer(
+              1U, 1U, 16U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire2_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire2_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire2", 64U, 64U)
+          << ConvolutionLayer(
+              1U, 1U, 16U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire3_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire3_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire3", 64U, 64U)
+          << ConvolutionLayer(
+              1U, 1U, 32U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire4_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire4_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire4", 128U, 128U)
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+          << ConvolutionLayer(
+              1U, 1U, 32U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire5_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire5_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire5", 128U, 128U)
+          << ConvolutionLayer(
+              1U, 1U, 48U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire6_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire6_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire6", 192U, 192U)
+          << ConvolutionLayer(
+              1U, 1U, 48U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire7_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire7_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire7", 192U, 192U)
+          << ConvolutionLayer(
+              1U, 1U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire8_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire8_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire8", 256U, 256U)
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 3, PadStrideInfo(2, 2, 0, 0, DimensionRoundingType::CEIL)))
+          << ConvolutionLayer(
+              1U, 1U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire9_squeeze1x1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/fire9_squeeze1x1_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << get_expand_fire_node(data_path, "fire9", 256U, 256U)
+          << ConvolutionLayer(
+              1U, 1U, 1000U,
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv10_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/squeezenet_v1.0_model/conv10_b.npy"),
+              PadStrideInfo(1, 1, 0, 0))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::AVG))
+          << FlattenLayer()
+          << SoftmaxLayer()
+          << Tensor(get_output_accessor(label, 5));
+
+    graph.run();
+}
+
+/** Main program for Squeezenet v1.0
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+int main(int argc, const char **argv)
+{
+    return arm_compute::utils::run_example(argc, argv, main_graph_squeezenet);
+}
\ No newline at end of file
diff --git a/examples/graph_vgg16.cpp b/examples/graph_vgg16.cpp
new file mode 100644
index 0000000..cac38d3
--- /dev/null
+++ b/examples/graph_vgg16.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/graph/Graph.h"
+#include "arm_compute/graph/Nodes.h"
+#include "support/ToolchainSupport.h"
+#include "utils/GraphUtils.h"
+#include "utils/Utils.h"
+
+#include <cstdlib>
+
+using namespace arm_compute::graph;
+using namespace arm_compute::graph_utils;
+
+/** Example demonstrating how to implement VGG16's network using the Compute Library's graph API
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+void main_graph_vgg16(int argc, const char **argv)
+{
+    std::string data_path; /* Path to the trainable data */
+    std::string image;     /* Image data */
+    std::string label;     /* Label data */
+
+    constexpr float mean_r = 123.68f;  /* Mean value to subtract from red channel */
+    constexpr float mean_g = 116.779f; /* Mean value to subtract from green channel */
+    constexpr float mean_b = 103.939f; /* Mean value to subtract from blue channel */
+
+    // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+    TargetHint            target_hint      = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+    ConvolutionMethodHint convolution_hint = ConvolutionMethodHint::DIRECT;
+
+    // Parse arguments
+    if(argc < 2)
+    {
+        // Print help
+        std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 2)
+    {
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 3)
+    {
+        data_path = argv[2];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+        std::cout << "No image provided: using random values\n\n";
+    }
+    else if(argc == 4)
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+        std::cout << "No text file with labels provided: skipping output accessor\n\n";
+    }
+    else
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        label     = argv[4];
+    }
+
+    Graph graph;
+
+    graph << target_hint
+          << convolution_hint
+          << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+                    get_input_accessor(image, mean_r, mean_g, mean_b))
+          << ConvolutionMethodHint::DIRECT
+          // Layer 1
+          << ConvolutionLayer(
+              3U, 3U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 2
+          << ConvolutionLayer(
+              3U, 3U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv1_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 3
+          << ConvolutionLayer(
+              3U, 3U, 128U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 4
+          << ConvolutionLayer(
+              3U, 3U, 128U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv2_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 5
+          << ConvolutionLayer(
+              3U, 3U, 256U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 6
+          << ConvolutionLayer(
+              3U, 3U, 256U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 7
+          << ConvolutionLayer(
+              3U, 3U, 256U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv3_3_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 8
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 9
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 10
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv4_3_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 11
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 12
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 13
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/conv5_3_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 14
+          << FullyConnectedLayer(
+              4096U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc6_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc6_b.npy"))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 15
+          << FullyConnectedLayer(
+              4096U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc7_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc7_b.npy"))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 16
+          << FullyConnectedLayer(
+              1000U,
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc8_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg16_model/fc8_b.npy"))
+          // Softmax
+          << SoftmaxLayer()
+          << Tensor(get_output_accessor(label, 5));
+
+    // Run graph
+    graph.run();
+}
+
+/** Main program for VGG16
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+int main(int argc, const char **argv)
+{
+    return arm_compute::utils::run_example(argc, argv, main_graph_vgg16);
+}
diff --git a/examples/graph_vgg19.cpp b/examples/graph_vgg19.cpp
new file mode 100644
index 0000000..49ae0fe
--- /dev/null
+++ b/examples/graph_vgg19.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/graph/Graph.h"
+#include "arm_compute/graph/Nodes.h"
+#include "support/ToolchainSupport.h"
+#include "utils/GraphUtils.h"
+#include "utils/Utils.h"
+
+#include <cstdlib>
+
+using namespace arm_compute::graph;
+using namespace arm_compute::graph_utils;
+
+/** Example demonstrating how to implement VGG19's network using the Compute Library's graph API
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+void main_graph_vgg19(int argc, const char **argv)
+{
+    std::string data_path; /* Path to the trainable data */
+    std::string image;     /* Image data */
+    std::string label;     /* Label data */
+
+    constexpr float mean_r = 123.68f;  /* Mean value to subtract from red channel */
+    constexpr float mean_g = 116.779f; /* Mean value to subtract from green channel */
+    constexpr float mean_b = 103.939f; /* Mean value to subtract from blue channel */
+
+    // Set target. 0 (NEON), 1 (OpenCL). By default it is NEON
+    TargetHint            target_hint      = set_target_hint(argc > 1 ? std::strtol(argv[1], nullptr, 10) : 0);
+    ConvolutionMethodHint convolution_hint = ConvolutionMethodHint::DIRECT;
+
+    // Parse arguments
+    if(argc < 2)
+    {
+        // Print help
+        std::cout << "Usage: " << argv[0] << " [target] [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 2)
+    {
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " [path_to_data] [image] [labels]\n\n";
+        std::cout << "No data folder provided: using random values\n\n";
+    }
+    else if(argc == 3)
+    {
+        data_path = argv[2];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " [image] [labels]\n\n";
+        std::cout << "No image provided: using random values\n\n";
+    }
+    else if(argc == 4)
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        std::cout << "Usage: " << argv[0] << " " << argv[1] << " " << argv[2] << " " << argv[3] << " [labels]\n\n";
+        std::cout << "No text file with labels provided: skipping output accessor\n\n";
+    }
+    else
+    {
+        data_path = argv[2];
+        image     = argv[3];
+        label     = argv[4];
+    }
+
+    Graph graph;
+
+    graph << target_hint
+          << convolution_hint
+          << Tensor(TensorInfo(TensorShape(224U, 224U, 3U, 1U), 1, DataType::F32),
+                    get_input_accessor(image, mean_r, mean_g, mean_b))
+          // Layer 1
+          << ConvolutionLayer(
+              3U, 3U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 64U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv1_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 2
+          << ConvolutionLayer(
+              3U, 3U, 128U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 128U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv2_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 3
+          << ConvolutionLayer(
+              3U, 3U, 256U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 256U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 256U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_3_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 256U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv3_4_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 4
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_3_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv4_4_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 5
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_1_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_2_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_3_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << ConvolutionLayer(
+              3U, 3U, 512U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/conv5_4_b.npy"),
+              PadStrideInfo(1, 1, 1, 1))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          << PoolingLayer(PoolingLayerInfo(PoolingType::MAX, 2, PadStrideInfo(2, 2, 0, 0)))
+          // Layer 6
+          << FullyConnectedLayer(
+              4096U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc6_b.npy"))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 7
+          << FullyConnectedLayer(
+              4096U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc7_b.npy"))
+          << ActivationLayer(ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::RELU))
+          // Layer 8
+          << FullyConnectedLayer(
+              1000U,
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_w.npy"),
+              get_weights_accessor(data_path, "/cnn_data/vgg19_model/fc8_b.npy"))
+          // Softmax
+          << SoftmaxLayer()
+          << Tensor(get_output_accessor(label, 5));
+
+    // Run graph
+    graph.run();
+}
+
+/** Main program for VGG19
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Arguments ( [optional] Target (0 = NEON, 1 = OpenCL), [optional] Path to the weights folder, [optional] image, [optional] labels )
+ */
+int main(int argc, const char **argv)
+{
+    return arm_compute::utils::run_example(argc, argv, main_graph_vgg19);
+}